package value_compare.framework;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.util.stream.Stream;

/**
 * @author lihao
 * @since 2019-11-03 21:24:11
 */
@Getter
public enum CompareOperator {
    /**
     * 大于
     */
    gt(">", MethodReference.M_GT,"大于"),
    /**
     * 大于等于
     */
    ge(">=", MethodReference.M_GE,"大于等于"),
    /**
     * 小于
     */
    lt("<",MethodReference.M_LT,"小于"),
    /**
     * 小于等于
     */
    le("<=",MethodReference.M_LE,"小于等于"),
    /**
     * 等于
     */
    eq("==",MethodReference.M_EQ,"等于"),
    /**
     * 不等于
     */
    ne("!=",MethodReference.M_NE,"不等于"),
    /**
     * 部分包含
     */
    containsAny("(-)",MethodReference.M_CONTAINSANY,"部分包含"),
    /**
     * 全部包含
     */
    containsAll("(+)",MethodReference.M_CONTAINSALL,"全部包含"),
    /**
     * 不包含
     */
    notContains("!(-)",MethodReference.M_NOTCONTAINS,"不包含");
    /**
     * 符号
     */
    private String symbol;
    /**
     * 比较方法
     */
    private Method comparableMethod;
    /**
     * 描述
     */
    private String desc;

    CompareOperator(String symbol, Method comparableMethod, String desc){
        this.symbol = symbol;
        this.comparableMethod = comparableMethod;
        this.desc = desc;
    }

    /**
     *
     * @param symbol symbol literals
     * @return the matched enum
     */
    public static CompareOperator fromSymbol(String symbol){
        return Stream.of(values()).filter(e->e.symbol.equals(symbol))
                .findFirst().orElse(null);
    }

    @Slf4j
    private static class MethodReference{
        private static Method M_GT,M_GE,M_LT,M_LE,M_EQ,M_NE,M_CONTAINSANY,M_CONTAINSALL,M_NOTCONTAINS;
        static {
            try {
                M_GT = AbstractComparable.class.getDeclaredMethod("gt");
                M_GE = AbstractComparable.class.getDeclaredMethod("ge");
                M_LT = AbstractComparable.class.getDeclaredMethod("lt");
                M_LE = AbstractComparable.class.getDeclaredMethod("le");
                M_EQ = AbstractComparable.class.getDeclaredMethod("eq");
                M_NE = AbstractComparable.class.getDeclaredMethod("ne");
                M_CONTAINSANY = AbstractComparable.class.getDeclaredMethod("containsAny");
                M_CONTAINSALL = AbstractComparable.class.getDeclaredMethod("containsAll");
                M_NOTCONTAINS = AbstractComparable.class.getDeclaredMethod("notContains");
            } catch (NoSuchMethodException e) {
                log.error("Init MethodReference error...",e);
            }
        }
    }
}
